const {
	sleepRandom,
	getDocument,
	getWindow,
	getParams,
	getResponse,
	getMaxResponse,
	getMSTime,
} = require('../index')
const _DBMongo = require('../db-mongo')

const _Task = require('../dao-mongo/Task')

let _task = null

process.on('error', (...args) => {
	console.log('error', args)
	if (_task) {
		return _task.stop({
			onError: args,
		}).then(r => {
			process.exit(1)
		})
	}
	process.exit(1)
})

process.on('exit', val => {
	console.log('---exit---', val)
	if (_task) {
		return _task.stop({
			onExit: val,
		})
	}
})

process.on('disconnect', (...args) => {
	console.log('disconnect', args)
	if (_task) {
		return _task.stop({
			onDisconnect: args
		}).then(r => {
			process.exit(1)
		})
	}
	process.exit(1)
})

process.on('abort', (...args) => {
	console.log('abort', args)
	if (_task) {
		return _task.stop({
			onAbort: args
		}).then(r => {
			process.exit(1)
		})
	}
	process.exit(1)
})

process.on('SIGINT', (...args) => {
	if (_task) {
		return _task.stop({
			onSIGINT: args,
		}).then(r => {
			process.exit(0)
		})
	}
	process.exit(0)
})

/**
 * 获取可执行任务
 * @param  {[type]} _id  [description]
 * @param  {[type]} init [description]
 * @return {[type]}      [description]
 */
async function getTask() {
	let _id = this._id
	let init = this.init
	let set = {
		status: 1,
		start_time: getMSTime(),
	}
	this.__single = false
	if (_id) {
		let status = parseInt(_id)
		if (_id.length == 1 && status == 2) {
			this.filter['status'] = status
		} else {
			this.filter['_id'] = _DBMongo.ObjectID(_id)
			this.__single = true
		}
		this.filter['_type_.id'] = this.typeId
		this.filter['_cate_.id'] = this.cateId
		set._stop = null
		set.duration = 0
		if (init == 'init') {
			await this.__init()
			delete this.filter.status
			set.pid = 0
			set.num = 0
			set._idx_ = 0
			set.total = 0
		}
		console.log('---this.filter---', this.filter)
		await _Task.findOneAndUpdate(this.filter, set);
		return _Task.findOne(this.filter);
	}
	this.filter['_type_.id'] = this.typeId
	this.filter['_cate_.id'] = this.cateId
	this.filter['status'] = 0

	let result = await _Task.findOneAndUpdate(this.filter, set);
	if (result && result.value && result.value._id)
		return _Task.findOne({
			_id: result.value._id
		});
	this.filter['_type_.id'] = this.typeId
	this.filter['_cate_.id'] = this.cateId
	// this.filter['num'] = 0
	this.filter['status'] = 2
	result = await _Task.findOneAndUpdate(this.filter, set);
	if (result && result.value && result.value._id)
		return _Task.findOne({
			_id: result.value._id
		});
	return null
}

async function run() {
	let value = await getTask.call(this)
	let maxTask = this.maxTask || -1
	let taskIdx = 0
	while (value && value._id) {
		taskIdx += 1
		if (maxTask > 0 && taskIdx > maxTask)
			break;
		await doTask.call(this, value)
		if (this.__single === true)
			break;
		value = await getTask.call(this)
	}
	return 'done'
}

/**
 * 执行任务
 * @param  {[type]} value   [description]
 * @return {[type]}         [description]
 */
async function doTask(value) {
	this.__task = _task = new _Task(value)
	_task.update({
		pid: process.pid
	})
	let success = await this.handler()
	if (success)
		return _task.done()
	return _task.stop()
}

// 状态 (
// 0: 待处理 
// 1: 运行中 
// -1: 完成 
// 2: 已停止)

module.exports = class TaskBaseFactory {

	constructor(typeId, cateId, filter) {
		let arg2 = process.argv[2]
		if (parseInt(arg2) > 0)
			this.maxTask = arg2
		else
			this._id = arg2
		this.init = process.argv[3]
		this.typeId = typeId
		this.cateId = cateId
		this.filter = filter && typeof filter == 'object' ? filter : {}
	}

	__init() {
		return Promise.resolve(true)
	}

	handler(task) {
		return Promise.resolve(false)
	}

	run() {
		return run.call(this).then(r => {
			console.log(`[${getMSTime()}]`, `[${process.pid}]`, '---TaskBaseFactory--r---', r)
			setTimeout(() => {
				process.exit(0)
			}, 180000)
		}).catch(err => {
			console.log(`[${getMSTime()}]`, `[${process.pid}]`, '---err---', err)
			if (_task) {
				let code = err.code
				let message = err.message
				let stack = err.stack
				if (err.err) {
					code = err.err.code
					message = err.err.message
					stack = err.err.stack
				}
				let stopErr = {
					catchError: {
						code,
						message,
						stack,
						err,
					},
				}
				stopErr = JSON.stringify(stopErr)
				return _task.stop(stopErr).then(r => {
					process.exit(1)
				}).catch(err => {
					console.log(`[${getMSTime()}]`, `[task stop error]`, `[${stopErr}]`, '---err---', err)
					process.exit(1)
				})
			}
			process.exit(1)
		})
	}
}